Skip to Content

09. Guardrails 与 Observability

本章参考 OpenAI agent safety 文档、LangChain / LangGraph 关于 LangSmith 的最新文档、OpenTelemetry GenAI Semantic Conventions、以及 Langfuse / Phoenix 等开源 LLM observability 方案。

本章高频面试题

  1. 什么是 Guardrails?它和普通的安全提示词有什么区别?
  2. 为什么说 Guardrails 不能只靠 Prompt,而必须是系统级能力?
  3. 输入 Guardrails、上下文 Guardrails、输出 Guardrails、工具 Guardrails、执行路径 Guardrails 分别是什么?
  4. 什么是 Observability?它和日志记录有什么区别?
  5. 为什么 Agent 比普通后端服务更需要 Observability?
  6. OpenTelemetry GenAI Semantic Conventions 当前是什么状态?应该怎么用?
  7. LangSmith、Langfuse、Phoenix、Helicone 应该怎么选?
  8. 一个生产级 Agent 系统最少应该监控哪些指标?
  9. 如何用 trace、run、thread 这些概念去理解 Agent 观测体系?
  10. Guardrails 和 Human-in-the-loop 有什么关系?什么时候该拦截,什么时候该审批?
  11. LLM-as-judge 怎么做才可靠?怎么避免裁判偏见?
  12. Evals 类型(offline、online、human、deterministic)怎么组合?
  13. Prompt/model 升级的灰度与回滚怎么做?

1. 什么是 Guardrails

Guardrails 可以理解成:

围绕 Agent 输入、上下文、输出、工具调用和执行路径设置的一组约束、检查和拦截机制,用来降低错误、滥用和风险。

它不是一个单一组件,而是一整套策略。常见 Guardrails:

  • 输入检查
  • 上下文检查
  • 输出检查
  • 工具调用前校验
  • 权限和审批门禁
  • 结构化输出校验
  • 风险内容拦截

一句话:

Guardrails 就是让 Agent”不能想怎么做就怎么做”的一套安全和质量边界。

2. Guardrails 和 Prompt 的区别

在 system prompt 里写规则只是”最弱的一层”。

Prompt 的作用是:告诉模型应该怎么做、提醒模型遵守规则。

但真正的 Guardrails 必须还包括:

  • 程序化检查
  • 拦截
  • 审批
  • 校验
  • 降级或失败处理

因为 Prompt 无法保证:

  • 模型一定听话
  • 外部内容不会污染模型
  • 高风险工具不会被误调用

结论:

Prompt 可以表达 Guardrails 意图,但 Guardrails 不能只靠 Prompt 实现。

3. Guardrails 的几个层次

3.1 输入 Guardrails

在模型处理用户输入前先做检查:

  • PII 检测和脱敏(Presidio、LlamaGuard)
  • Jailbreak / injection 检测(Prompt Guard、Rebuff)
  • 非法内容、仇恨言论、未成年相关内容
  • Input token budget 限制

OpenAI、Anthropic 官方安全文档都明确推荐这一层。

3.2 上下文 Guardrails(容易被忽略)

不只是用户输入,外部检索结果、网页内容、工具返回文本也可能带来注入风险。

  • 不要把不可信文本直接当成指令
  • 把外部内容和系统规则明确分层(XML tags、section headers)
  • 优先抽取结构化字段,而不是把整段任意文本直接串进关键决策链路
  • 已知的 injection 模式用 regex/分类器预过滤

3.3 输出 Guardrails

模型产出后再检查:

  • JSON Schema 校验(Zod、io-ts)
  • 敏感信息扫描(PII、API key、内部 URL)
  • 格式合规(引用格式、链接白名单)
  • 违规内容二次分类(LlamaGuard output version)
  • 字数/token 上限(避免失控生成)

3.4 工具 Guardrails

工具调用前后做检查:

  • 参数 schema 校验
  • 参数值域 allowlist(邮件域名、金额上限)
  • 权限校验(principal 有没有权限调这个工具)
  • 风险等级判断和审批触发
  • 工具返回结果是否合法

3.5 执行路径 Guardrails

Agent 的执行流程本身也需要 Guardrails:

  • 最大步数限制
  • 最大重试次数
  • 最大同类工具调用次数(避免循环)
  • 禁止某些危险组合路径(搜索 → 直接发邮件 链路需要人工介入)
  • Budget circuit breaker(见第 5 章)

4. Guardrails 的工程方法论

4.1 先识别风险,再决定 Guardrails

不要为了”看起来专业”就堆很多 Guardrails。先问清楚:

  1. 系统会处理什么数据
  2. 会执行什么动作
  3. 哪些错误代价最高
  4. 哪些内容来自不可信源

然后按风险分层去设计 Guardrails。

4.2 优先做程序化 Guardrails

稳定的顺序:

  1. 权限和工具可见性控制
  2. 输入/输出 schema 校验
  3. 高风险动作审批(HITL)
  4. 内容检测和分类(LLM classifier)
  5. Prompt 级提醒(最弱一层)

真正可靠的 Guardrails 通常更像系统设计,而不是提示词写作。

4.3 对外部内容默认不完全信任

OpenAI 官方安全文档强调的原则:

不要让不可信文本直接驱动高风险行为。

常见来源:检索到的网页、外部邮件、第三方 API 返回、MCP server 的 tool description。治理见第 8 章。

5. Guardrail 工具选型

  • Llama Guard (Meta):开源、双向(输入+输出)分类器,轻量,自托管友好
  • Prompt Guard (Meta):专用 injection/jailbreak 分类
  • NeMo Guardrails (NVIDIA):规则 + LLM 双层,支持 Colang DSL,功能最全
  • Rebuff (ProtectAI):专注 prompt injection,多层防御
  • Presidio (Microsoft):PII 检测与脱敏,成熟稳定
  • OpenAI Moderation API:托管的内容审核,免费,覆盖 OpenAI policies

选型原则:

  • 自托管优先 Llama Guard + Presidio
  • 需要规则可配置(合规场景)用 NeMo Guardrails
  • OpenAI 生态内默认开启 Moderation

6. 什么是 Observability

Observability 不是简单写日志,而是:

让你能够通过系统输出的数据,理解 Agent 当时做了什么、为什么这么做、在哪一步出错、问题属于哪一类。

在 Agent 系统里,这意味着你需要能看到:

  • 模型调用(prompt、response、usage、latency、cost)
  • 工具调用(name、args、result、error)
  • 检索结果(query、hits、scores)
  • 规划步骤(plan snapshot、decision log)
  • 中断和恢复(interrupt payload、resume decision)
  • 最终输出

7. 为什么 Agent 比普通后端更需要 Observability

Agent 系统更复杂:模型不确定性、多步执行、外部工具、上下文动态变化、中间状态。

普通接口出错只需要看 request / response / stack trace。 Agent 出错需要知道:

  • 当时看到了哪些 context
  • 选了哪个工具
  • 为什么选它
  • 检索到了什么
  • 中间有没有重试
  • 哪一步开始跑偏
  • 对应的 prompt 版本和模型版本

这就是为什么 LangChain / LangGraph 文档把 Observability 放得很重要,并通过 LangSmith 强调 traces / runs / threads 这套模型。

8. 核心概念:Trace、Run、Thread

按 LangSmith 官方文档的定义:

8.1 Trace

一次完整操作的执行轨迹——“用户发起一个任务,到最终结果返回”的整条链路。

8.2 Run

Trace 里的一个执行步骤:一次 LLM 调用、一次 tool call、一次检索、一个子链路。

8.3 Thread

把多次相关 trace 串起来的一条长会话或长任务上下文。

这个模型天然支持:

  • 单次任务排障
  • 多轮会话分析
  • 跨步骤性能诊断

9. OpenTelemetry GenAI Semantic Conventions

这是 Agent observability 的工业级事实标准,虽然当前(2026-04)仍处于 development 状态。

9.1 当前状态

OTel 社区 2024 年启动 GenAI SIG,定义了 LLM / Agent / tool call 的统一 span 属性和 metric 命名。当前状态:

  • Development(非 stable),但已被多家 vendor 采用
  • 通过环境变量 OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental 启用最新版
  • 已有针对 Anthropic / OpenAI / Azure AI Inference / AWS Bedrock / MCP 的技术特定约定

9.2 关键 Span 类型

  • LLM call spangen_ai.operation.name = "chat" | "generate_content" | ...
  • Agent span:表示一次 agent run
  • Tool call span:表示工具调用
  • Embedding span / Rerank span

9.3 关键属性(示意)

  • gen_ai.systemopenai / anthropic / bedrock / mcp
  • gen_ai.request.model:请求的模型 ID
  • gen_ai.response.model:实际响应的模型(可能不同于请求,例如 fallback)
  • gen_ai.usage.input_tokens / gen_ai.usage.output_tokens / gen_ai.usage.total_tokens
  • gen_ai.request.temperature / gen_ai.request.top_p / gen_ai.request.max_tokens
  • gen_ai.response.finish_reasons
  • Tool 调用相关:gen_ai.tool.name / gen_ai.tool.call.id

9.4 为什么值得走 OTel 规范

  • 跨 vendor 一致性:换 observability provider 不用重新 instrument
  • 和非 LLM 的可观测性打通:Agent tool call 可以和下游数据库/API 的 trace 串起来
  • 未来稳定性投资:stable 版本发布后,基础字段不会大改

实操上:业务代码用 OTel SDK + GenAI conventions 打点,后端可以同时发到 LangSmith / Langfuse / Phoenix / Jaeger。

10. LLM Observability 平台选型

平台类型适合场景
LangSmith托管LangChain 生态深度集成、trace 体验好
Langfuse开源 + 托管自托管友好、provider 无关、成本归因强
Phoenix (Arize)开源 + 托管OTel 原生、evals 框架强
Helicone托管代理型接入(改 baseURL 即可)、成本控制
Honeycomb / Datadog通用 APM已有通用 observability 栈的扩展
自研基于 OTel Collector + Grafana极致定制、合规场景

选型原则:

  • 深度 LangChain 用户 → LangSmith
  • 多 provider、自托管、成本归因 → Langfuse
  • 重度 evals + OTel 原生 → Phoenix
  • 快速接入、最低侵入 → Helicone
  • 已有 Datadog/Honeycomb → 走 OTel 打通

11. 生产级 Agent 最少应该观测什么

11.1 运行指标

  • Run 成功率 / 失败率
  • 平均时延、p95、p99(尾延迟才是真相)
  • 首包时延 (TTFB)
  • 平均 token 消耗(prompt + completion)
  • 平均成本($USD)
  • Trajectory 长度(步数分布)

11.2 模型指标

  • 模型调用次数
  • Prompt cache 命中率(非常关键,见第 3 章)
  • 结构化输出失败率
  • 模型错误率 / fallback 触发率
  • Per-provider 可用性(多 provider 路由必须观测)

11.3 工具指标

  • 工具选择准确率 + specificity(不该调用时没调)
  • 参数填充正确率
  • 工具成功率
  • 参数校验失败率
  • 平均工具耗时
  • 高风险工具审批通过率
  • Idempotency key 重复命中率(反映重试/去重健康度)

11.4 检索指标

  • Top-k 命中率
  • 召回延迟
  • Rerank 后命中率
  • 空召回率
  • Contextual retrieval 的 context generation 失败率

11.5 人工介入指标

  • HITL 触发率
  • 审批拒绝率
  • 审批后修改率
  • 审批平均耗时(影响用户体验)
  • 超时审批率

11.6 成本归因

  • Per-workspace / per-user / per-feature / per-tool 的 token + $ 归因
  • 单任务平均成本的时间趋势
  • Prompt cache 带来的节省

12. Observability 不只是 tracing

完整的 Observability 至少包括:

  1. Tracing:看执行链路和每一步细节
  2. Metrics:看成功率、耗时、成本、错误率等宏观指标
  3. Logs:看原始事件、错误信息和上下文记录
  4. Feedback / Annotation:看人工反馈和质量标注(thumbs up/down、纠正、标签)
  5. Evaluations:看系统在标准任务集上的表现

如果只有日志,没有 trace、指标和评估,严格来说还不算完整可观测。

13. Evals:让”好”变得可度量

Evals 是把 Agent 从”看着差不多”做到”真的能上线”的关键。

13.1 Evals 分类

  • Deterministic evals:字符串匹配、regex、JSON schema 校验、数值精确比对。适合确定性输出
  • LLM-as-judge:用另一个(通常更强的)LLM 按 rubric 打分。适合开放式任务
  • Human evals:人工标注,代价最高但最准
  • Online evals:从生产流量采样 + feedback 自动评估
  • A/B evals:同一请求跑两个 prompt/model 版本,结果对比

13.2 LLM-as-judge 的最佳实践

LLM-as-judge 是最容易做错的一环,几条工程规矩:

  • 结构化 rubric:不要让 judge 打个 1-10,让它按多个维度分别判定(事实准确、格式合规、未幻觉、引用正确),返回 JSON
  • 避免 position bias:pairwise 比较时随机化顺序,或同时跑两个顺序取平均
  • 避免 self-preference:判官不要和被评估的模型是同一个(或至少做交叉)
  • Few-shot:给 judge 2-3 个带标注的例子,校准它的判断
  • 一致性检测:同一个样本跑多次,判官结果应该一致;不一致的样本标记为 low confidence
  • 和人工 gold 校准:judge 的判断要定期和人工标注对齐,漂移了就更新 prompt

13.3 Eval 数据集的层次

  • Gold set:人工精标的标准集,规模 50-200 条覆盖核心场景
  • Adversarial set:故意构造的 badcase(容易误触发、边界条件、对抗输入)
  • 回归集:历史 bugfix 和 feature 验证样本,每次迭代必过
  • 真实流量采样:生产里随机采样 + 脱敏,反映真实分布

13.4 Eval 放在 CI

  • Prompt / model / skill / tool 任何变更必须跑回归集
  • 指标有阈值,下降超阈值阻塞合并
  • Eval 结果有历史趋势,看长期变化
  • 成本 / 延迟 / trajectory 长度也是 eval 指标,不只有”对不对”

14. Prompt / Model 升级的灰度和回滚

模型供应商升级(Opus 4.6 → 4.7)或自己改 prompt,不能直接全量切换。

14.1 灰度模式

  • Shadow mode:新旧 prompt/model 同时跑,只用旧版本的结果返回给用户,新版本结果只记录用于对比
  • Canary:新版本放 1% → 5% → 20% → 100%,每阶段看指标
  • User segmentation:按 workspace、role、geography 分组灰度
  • Feature flag:运行时开关,一键回滚

14.2 必须监控的回归指标

  • 任务成功率
  • P95 延迟
  • Trajectory 长度
  • 成本
  • Tool call 准确率
  • Prompt cache 命中率(换模型可能破坏缓存)
  • 用户 thumbs-down 率

任何一项退步超阈值 → 自动回滚,不等人决定。

15. TypeScript 示例:给一次 run 打 trace metadata + OTel 约定

import { trace, SpanKind } from "@opentelemetry/api"; const tracer = trace.getTracer("agent-runtime"); type AgentRunInput = { runId: string; threadId: string; userId: string; workspaceId: string; promptVersion: string; model: string; taskType: string; }; export async function runAgent<T>( input: AgentRunInput, fn: () => Promise<T> ): Promise<T> { return tracer.startActiveSpan( "agent.run", { kind: SpanKind.INTERNAL, attributes: { // OTel GenAI conventions "gen_ai.system": "anthropic", "gen_ai.request.model": input.model, "gen_ai.operation.name": "agent", // 业务维度 "agent.run_id": input.runId, "agent.thread_id": input.threadId, "agent.task_type": input.taskType, "agent.prompt_version": input.promptVersion, "user.id": input.userId, "workspace.id": input.workspaceId, }, }, async (span) => { try { const result = await fn(); span.setStatus({ code: 1 }); // OK return result; } catch (err) { span.recordException(err as Error); span.setStatus({ code: 2, message: (err as Error).message }); throw err; } finally { span.end(); } } ); }

这个例子体现几点:

  • 用 OTel GenAI conventions 做跨 vendor 一致的打点
  • 业务维度(workspace.id 等)作为附加属性,便于归因和过滤
  • 异常自动记录到 span
  • Cost/latency 可以由 OTel Collector 聚合成 metrics

16. Guardrails 和 Observability 的闭环

成熟系统里,这两者不是分离的:

  1. Guardrails 在运行时做拦截和校验
  2. Observability 记录 Guardrails 触发点(为什么被拦、哪类输入触发)
  3. 失败样本 进入 eval 集和人工分析
  4. 反过来优化 prompt、工具边界和 Guardrails 规则

例如:

  • 某类工具误调用频繁 → trace 发现都来自同一类用户输入 → 补一个输入 Guardrail 或更严格的 tool visibility 规则
  • Prompt injection 在某些 indirect source 上高频 → 增加该 source 的 sanitization + dual-LLM
  • HITL 拒绝率在某类动作上异常高 → 调整默认参数或引入额外校验

这才叫系统性优化

17. Guardrails 和 Human-in-the-loop 的关系

  • Guardrails 更像自动边界和自动检查
  • HITL 更像关键节点的人类决策

两者协同:

  1. 先用 Guardrails 自动过滤明显风险(拦截 injection、schema 错误、越权)
  2. 对高风险但无法完全自动判断的动作,进入 HITL

Guardrails 负责自动防护,HITL 负责高风险兜底。

18. 什么时候说明你的系统”Guardrails 不够”

  • 模型经常看到不该看到的工具
  • 高风险工具误触发后才靠人工补救
  • 输出经常不符合 schema
  • 外部检索内容经常把模型带偏
  • 线上出错后看不到当时 context 和调用链
  • Prompt cache 命中率常年 < 50%
  • 没有 trace 或无法按 run_id 快速定位

这些信号说明问题不只是”模型偶发不稳定”,而是系统边界不清晰。

19. 本章方法论小结

  1. Guardrails 不是一句提示词,而是一整套系统边界(输入/上下文/输出/工具/执行路径)
  2. Prompt 只能表达规则,不能替代强制校验
  3. 对外部不可信内容默认要做隔离和结构化处理
  4. Observability 不只是日志,还包括 traces、metrics、feedback 和 evals
  5. OpenTelemetry GenAI Semantic Conventions 是跨 vendor 的事实标准(当前 experimental),值得作为打点基线
  6. LangSmith / Langfuse / Phoenix / Helicone 按场景选型,都可以和 OTel 协作
  7. Agent 观测体系应覆盖模型、工具、检索、审批、成本、trajectory 长度、prompt cache 命中率
  8. Evals 分 deterministic / LLM-judge / human / online,组合使用
  9. LLM-as-judge 必须结构化 rubric + 避免 position/self bias + 人工校准
  10. Prompt/model 升级走 shadow → canary → 全量,配套自动回滚
  11. Guardrails 和 Observability 应该组成”防护 + 诊断 + 迭代”的闭环
Last updated on